package com.knife.easyexcel.read.chain;

import com.knife.easyexcel.read.data.ImportDataWarp;
import com.knife.easyexcel.read.data.ImportValidatorContext;
import com.knife.easyexcel.read.data.ValidateElementResult;
import com.knife.easyexcel.read.message.ImportValidatorErrorMsgBuilder;
import com.knife.easyexcel.read.validator.ImportValidator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 过滤器链
 *
 * @author Win10
 * @created 2024年12月19日 星期四 10:09
 */
@Slf4j
public class BatchImportValidatorHelperChain<T> {
    /**
     * 本次导入的全量数据封装集合
     */
    private List<ImportDataWarp<T>> cuxImportDataWarpList;

    /**
     * 本校验链需要用到的校验器
     */
    private List<ImportValidator<T>> cuxImportValidatorList;

    /**
     * 校验失败的数据,异常信息生成工具
     */
    private ImportValidatorErrorMsgBuilder<T> cuxImportValidatorErrorMsgBuilder;

    /**
     * 校验链上下文
     */
    private ImportValidatorContext<T> cuxImportValidatorContext;

    public List<ImportDataWarp<T>> getCuxImportDataWarpList() {
        return cuxImportDataWarpList;
    }

    public void setCuxImportDataWarpList(List<ImportDataWarp<T>> cuxImportDataWarpList) {
        this.cuxImportDataWarpList = cuxImportDataWarpList;
    }

    public List<ImportValidator<T>> getCuxImportValidatorList() {
        return cuxImportValidatorList;
    }

    public void setCuxImportValidatorList(List<ImportValidator<T>> cuxImportValidatorList) {
        this.cuxImportValidatorList = cuxImportValidatorList;
    }

    public ImportValidatorErrorMsgBuilder<T> getCuxImportValidatorErrorMsgBuilder() {
        return cuxImportValidatorErrorMsgBuilder;
    }

    public void setCuxImportValidatorErrorMsgBuilder(ImportValidatorErrorMsgBuilder<T> cuxImportValidatorErrorMsgBuilder) {
        this.cuxImportValidatorErrorMsgBuilder = cuxImportValidatorErrorMsgBuilder;
    }

    public ImportValidatorContext<T> getCuxImportValidatorContext() {
        return cuxImportValidatorContext;
    }

    public void setCuxImportValidatorContext(ImportValidatorContext<T> cuxImportValidatorContext) {
        this.cuxImportValidatorContext = cuxImportValidatorContext;
    }

    public static class Builder<T> {
        private BatchImportValidatorHelperChain<T> chain = new BatchImportValidatorHelperChain<T>();

        public static <T> Builder<T> create() {
            return new Builder<T>();
        }

        public Builder<T> data(List<T> dataList) {
            chain.setCuxImportDataWarpList(new ArrayList<>());
            chain.setCuxImportValidatorList(new ArrayList<>());
            chain.setCuxImportValidatorContext(new ImportValidatorContext<>(dataList));
            // 将数据放入到包装类中
            dataList.forEach(item -> {
                ImportDataWarp<T> tCuxImportDataWarp = new ImportDataWarp<>(item);
                List<ImportDataWarp<T>> cuxImportDataWarpList = chain.getCuxImportDataWarpList();
                cuxImportDataWarpList.add(tCuxImportDataWarp);
            });
            return this;
        }

        public Builder<T> validator(ImportValidator<T> cuxImportValidator) {
            List<ImportValidator<T>> cuxImportValidatorList = chain.getCuxImportValidatorList();
            cuxImportValidatorList.add(cuxImportValidator);
            return this;
        }

        public Builder<T> validator(List<ImportValidator<T>> cuxImportValidatorList) {
            List<ImportValidator<T>> tCuxImportValidatorList = chain.getCuxImportValidatorList();
            tCuxImportValidatorList.addAll(cuxImportValidatorList);
            return this;
        }

        public Builder<T> errorMsgBuilder(ImportValidatorErrorMsgBuilder<T> errorMsgBuilder) {
            chain.setCuxImportValidatorErrorMsgBuilder(errorMsgBuilder);
            return this;
        }

        public BatchImportValidatorHelperChain<T> build() {
            return chain;
        }
    }

    /**
     * 添加过滤器链缓存,用于执行过滤前进行加入
     *
     * @param key      键
     * @param supplier 提供值
     */
    public void addChainCache(String key, Supplier<Object> supplier) {
        cuxImportValidatorContext.getChainCache().computeIfAbsent(key, k -> supplier.get());
    }

    /**
     * 校验链校验,会按照校验链中添加的校验器顺序进行遍历校验;当校验失败时,并且不为快速失败,则继续走后面的校验器;如果为快速失败,则不走后面的校验器
     *
     * @return 存在校验结果错误的数据，则返回false
     */
    public Boolean doValidate(Function<T, String> elementKeyFunc, List<ValidateElementResult<T>> validateElementResultList) {
        for (ImportDataWarp<T> tCuxImportDataWarp : cuxImportDataWarpList) {
            // 缓存清理
            cuxImportValidatorContext.getValidatorCache().clear();
            try {
                // 对每一条数据都进行链路校验
                for (ImportValidator<T> tCuxImportValidator : cuxImportValidatorList) {
                    // 本次校验结果，如果校验失败，则给本条数据打上标记
                    String validateResult = tCuxImportValidator.validate(tCuxImportDataWarp, cuxImportValidatorContext);
                    if (StringUtils.isNotEmpty(validateResult)) {
                        tCuxImportDataWarp.setFlag(false);
                        tCuxImportDataWarp.addErrorMsg(validateResult);
                        // 快速失败时，不需要走后面的校验了
                        if (Boolean.TRUE.equals(tCuxImportValidator.fastFail())) {
                            break;
                        }
                    }
                }
                // 校验之后，构造异常结果信息
                if (Boolean.FALSE.equals(tCuxImportDataWarp.getFlag())) {
                    String errorMsg = cuxImportValidatorErrorMsgBuilder.build(tCuxImportDataWarp);
                    validateElementResultList.add(new ValidateElementResult<>(false, elementKeyFunc.apply(tCuxImportDataWarp.getData()), tCuxImportDataWarp.getData(), errorMsg));
                } else {
                    validateElementResultList.add(new ValidateElementResult<>(true, elementKeyFunc.apply(tCuxImportDataWarp.getData()), tCuxImportDataWarp.getData()));
                }
            } catch (Exception e) {
                log.error("==> 校验链校验出现异常:{} <===", e.getMessage());
                // 这个错误字符串不允许省略，当空指针时，用于记录错误；否则导致空指针数据校验通过
                validateElementResultList.add(new ValidateElementResult<>(false, elementKeyFunc.apply(tCuxImportDataWarp.getData()), tCuxImportDataWarp.getData(), "异常:" + e.getMessage()));
            }
            cuxImportValidatorContext.getAlreadyValidatedImportDataWarpList().add(tCuxImportDataWarp);
        }
        // 清理缓存
        cuxImportValidatorContext.clearChainCache();
        // 有一条失败则为失败
        return validateElementResultList.stream().allMatch(ValidateElementResult::getFlag);
    }
}
